################################################################################
# Copyright (C) 2008 Michiel Helvensteijn                                      #
#                                                                              #
# This file is part of the Mist compiler.                                      #
#                                                                              #
# The Mist compiler is free software: you can redistribute it and/or modify    #
# it under the terms of the GNU General Public License as published by         #
# the Free Software Foundation, either version 3 of the License, or            #
# (at your option) any later version.                                          #
#                                                                              #
# The Mist compiler is distributed in the hope that it will be useful,         #
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
# GNU General Public License for more details.                                 #
#                                                                              #
# You should have received a copy of the GNU General Public License            #
# along with the Mist compiler.  If not, see <http://www.gnu.org/licenses/>.   #
################################################################################

################################################################################
ROOT = .
################################################################################

BISON = bison
FLEX  = flex
CXX   = g++
RM    = rm -f
TOUCH = touch
ECHO  = echo
TAR   = tar
MKDIR = mkdir
CP    = cp
GREP  = grep

CXXFLAGS      = -pipe -Wall -Wno-parentheses -g -I$(ROOT)
LINKFLAGS     = -lgmpxx -lgmp -lboost_program_options
TESTLINKFLAGS = -lboost_test_exec_monitor -lboost_system -lboost_filesystem

################################################################################

PROGRAM_FILES = compiler

BISON_FILES = bisonparser.yy

FLEX_FILES = lexer.yy

SOURCE_FILES = ast/node.cpp          \
               ast/arraytype.cpp      \
               ast/assertion.cpp       \
               ast/assignment.cpp       \
               ast/idassignment.cpp      \
               ast/booleanliteral.cpp     \
               ast/null.cpp                \
               ast/booleantype.cpp          \
               ast/compoundstatement.cpp     \
               ast/declarations.cpp           \
               ast/arithmeticoperation.cpp     \
               ast/expression.cpp               \
               ast/functioncall.cpp              \
               ast/functiondeclaration.cpp        \
               ast/functiontype.cpp                \
               ast/ifstatement.cpp                 \
               ast/integerliteral.cpp              \
               ast/integertype.cpp                 \
               ast/subscripting.cpp                \
               ast/type.cpp                        \
               ast/unaryoperation.cpp              \
               ast/identifier.cpp                  \
               ast/variabledeclaration.cpp         \
               ast/voidtype.cpp                    \
               ast/whilestatement.cpp              \
               ast/comparisonchain.cpp             \
               ast/typeerror.cpp                   \
               ast/andchain.cpp                    \
               ast/orchain.cpp                     \
               ast/implieschain.cpp                \
               ast/forstatement.cpp                \
               ast/range.cpp                       \
               ast/rangetype.cpp                   \
               ast/reference.cpp                   \
               ast/booleanpointerliteral.cpp       \
               ast/integerpointerliteral.cpp       \
               visitors/visitor.cpp                \
               visitors/statementnavigator.cpp     \
               visitors/expressionnavigator.cpp    \
               visitors/universalnavigator.cpp     \
               visitors/cppvisitor.cpp             \
               visitors/echovisitor.cpp            \
               visitors/accesstypevisitor.cpp      \
               visitors/astvisitor.cpp             \
               visitors/declarationvisitor.cpp     \
               visitors/typevisitor.cpp            \
               visitors/findreferencesvisitor.cpp  \
               visitors/findtemporariesvisitor.cpp \
               visitors/sideeffectvisitor.cpp      \
               codeposition.cpp                    \
               codelocation.cpp                    \
               codestream.cpp                      \
               common.cpp                          \
               message.cpp                         \
               messages.cpp                        \
               messageinfo.cpp                     \
               options.cpp                         \
               path.cpp                            \
               assert.cpp                          \
               accesstype.cpp                      \
               symboltree.cpp                      \
               parameterpolicy.cpp

TEST_OUTPUT_FILES = 

################################################################################

SOURCES = $(BISON_FILES:.yy=.tab.cpp) $(FLEX_FILES:.yy=.lex.cpp) $(SOURCE_FILES)

OBJECTS = $(SOURCES:.cpp=.o)

PROGRAM_OBJECTS = $(PROGRAM_FILES:=.o)

DEPENDENCIES = $(SOURCES:.cpp=.d) compiler.d test/test.d

STATIC_BISON_HEADERS = location.hh position.hh stack.hh

ANY_BISON_FILE = $(firstword $(BISON_FILES))

GENERATED_HEADERS = $(STATIC_BISON_HEADERS)     \
                    $(BISON_FILES:.yy=.tab.hpp) \
                    $(FLEX_FILES:.yy=.lex.hpp)

################################################################################

.PHONY: all clean depclean test

.SECONDARY: $(OBJECTS) $(PROGRAM_OBJECTS) \
            $(BISON_FILES:.yy=.tab.cpp)   \
            $(FLEX_FILES:.yy=.lex.cpp)    \
            $(BISON_FILES:.yy=.tab.hpp)   \
            $(FLEX_FILES:.yy=.lex.hpp)    \
            test/test.o

.SUFFIXES:

################################################################################

all: $(PROGRAM_FILES) test

clean: depclean
	$(RM) *.o *.output *.lex.* *.tab.* *.hh $(PROGRAM_FILES) test/test test/tested test/*.o visitors/*.o ast/*.o

depclean:
	$(RM) *.d test/*.d visitors/*.d ast/*.d

test/test: $(OBJECTS) test/test.o
	@ $(ECHO) "Linking: <sources>.o $@.o"
	@ $(CXX) $(CXXFLAGS) $(LINKFLAGS) -o $@ $^ $(TESTLINKFLAGS)

test: test/tested
test/tested: test/test $(TEST_OUTPUT_FILES)
	@ BOOST_TEST_CATCH_SYSTEM_ERRORS="no" ./test/test
	@ touch test/tested

ifeq (,$(findstring $(MAKECMDGOALS), clean depclean))
-include $(DEPENDENCIES)
endif

%.lex.cpp %.lex.hpp: %.yy
	@ $(ECHO) $(FLEX) $<
	@ $(FLEX) $<

%.tab.cpp %.tab.hpp: %.yy
	$(BISON) $<
	@ touch -m position.hh --reference=codeposition.hpp
	@ touch -m location.hh --reference=codelocation.hpp
	@ touch -m stack.hh    --reference=codelocation.hpp

$(STATIC_BISON_HEADERS): $(ANY_BISON_FILE:.yy=.tab.cpp)

%.o: %.cpp
	@ $(ECHO) "Compiling: $<"
	@ $(CXX) $(CXXFLAGS) -c $< -o $@

%.d: %.cpp $(GENERATED_HEADERS)
	@ $(ECHO) "Finding dependencies: $<"
	@ $(SHELL) -ec '$(CXX) -MM -I$(ROOT) $< | sed '\''s!$(notdir $*)\.o[ :]*!$*.o $*.d : !'\'' > $@; [ -s $@ ] || $(RM) $@'

%: $(OBJECTS) %.o
	@ $(ECHO) "Linking: <sources>.o $*.o"
	@ $(CXX) $(CXXFLAGS) $(LINKFLAGS) -o $@ $^

################################################################################
